package com.mnsq.common.service.impl;

import com.mnsq.common.bean.condition.DocumentCondition;
import com.mnsq.common.bean.document.BaseDoc;
import com.mnsq.common.bean.dto.PageInfo;
import com.mnsq.common.service.MongoService;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.util.*;

/**
 * @author 周俭
 */
@Repository
public class MongoServiceImpl<T extends BaseDoc> implements MongoService<T> {
    private static String STR = "[,，：:]";

//    @Autowired
//    private ViewLogRepository viewLogRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void save(T t) {
        mongoTemplate.save(t);
    }

    @Override
    public void saveAll(Iterable<T> v) {
        for (T t : v) {
            this.save(t);
        }
    }

    @Override
    public PageInfo page(DocumentCondition documentCondition) {
        Query query = packageQuery(documentCondition);
        Class<T> doc = documentCondition.getDoc();
        List<T> documents = mongoTemplate.find(query, doc);
        long size = mongoTemplate.count(query, doc);
        PageInfo pg = new PageInfo();
        pg.setContent(documents);
        pg.setPageNum(documentCondition.getPageNum());
        pg.setTotalSize(size);
//      TODO 集成日志记录   if (CollectionUtils.isNotEmpty(documents) && ThreadLocalUserId.CURRENT_USER_ID.get() != null
//                && StringUtils.isNotBlank(MapUtils.getString(documentCondition.getEqParams(), "unique", null))) {
//            ViewLog log = new ViewLog();
//            log.setUnique(MapUtils.getString(documentCondition.getEqParams(), "unique"));
//            log.set
//            viewLogRepository.save(log);
//        }
        return pg;
    }

    @Override
    public void update(DocumentCondition documentCondition) {
        Query query = this.packageQuery(documentCondition);
        Update update = new Update();
        Map<String, String> updateParams = documentCondition.getUpdateParams();
        for (Map.Entry<String, String> mp : updateParams.entrySet()) {
            update.set(mp.getKey(), mp.getValue());
        }
        mongoTemplate.updateFirst(query, update, documentCondition.getDoc());
    }

    private Query packageQuery(DocumentCondition documentCondition) {
        // 需要查询显示的字段
        DBObject fields = new BasicDBObject();
        String fds = documentCondition.getQueryColumns();
        if (StringUtils.isNotBlank(fds)) {
            for (String s : fds.split(STR)) {
                fields.put(s, 1);
            }
        }
        List<String> columns = new ArrayList<>();
        Criteria criteria = new Criteria();
        boolean statusCheck = false;
        if (MapUtils.isNotEmpty(documentCondition.getEqParams())) {
            Map<String, Object> queryParams = documentCondition.getEqParams();
            for (Map.Entry<String, Object> mp : queryParams.entrySet()) {
                if (columns.contains(mp.getKey())) {
                    continue;
                }
                columns.add(mp.getKey());
                if ("status".equals(mp.getKey())) {
                    statusCheck = true;
                }
                criteria.and(mp.getKey()).is(mp.getValue());
            }
        }
        // 默认查询状态有效的数据
        if (!statusCheck) {
            criteria.and("status").is(1);
        }
        if (MapUtils.isNotEmpty(documentCondition.getLkParams())) {
            Map<String, String> lkParams = documentCondition.getEqParams();
            for (Map.Entry<String, String> mp : lkParams.entrySet()) {
                if (columns.contains(mp.getKey())) {
                    continue;
                }
                columns.add(mp.getKey());
                criteria.and(mp.getKey()).regex(".*" + mp.getValue() + ".*");
            }
        }
        if (MapUtils.isNotEmpty(documentCondition.getInParams())) {
            Map<String, String> inParams = documentCondition.getInParams();
            for (Map.Entry<String, String> mp : inParams.entrySet()) {
                if (columns.contains(mp.getKey())) {
                    continue;
                }
                columns.add(mp.getKey());
                criteria.and(mp.getKey()).in(Arrays.asList(mp.getValue().split(STR)));
            }
        }
        // 创建时间区间查询
        if (documentCondition.getStartTime() != null && documentCondition.getEndTime() != null) {
            criteria.and("createTime").gte(documentCondition.getStartTime()).lte(documentCondition.getEndTime());
        } else if (documentCondition.getStartTime() != null) {
            criteria.and("createTime").gte(documentCondition.getStartTime());
        } else if (documentCondition.getEndTime() != null) {
            criteria.and("createTime").lte(documentCondition.getEndTime());
        }
        Query query = new BasicQuery(new BasicDBObject().toString(), fields.toString());
        query.with(PageRequest.of(documentCondition.getPageNum(), documentCondition.getPageSize()));
        if (MapUtils.isNotEmpty(documentCondition.getSortParams())) {
            Sort sort = null;
            Set<Map.Entry<String, Integer>> set = documentCondition.getSortParams().entrySet();
            for (Map.Entry<String, Integer> mp : set) {
                // 1 为正序，其他为倒序
                if (sort == null) {
                    if (mp.getValue() != null && mp.getValue() == 1) {
                        sort = Sort.by(mp.getKey()).ascending();
                    } else {
                        sort = Sort.by(mp.getKey()).descending();
                    }
                } else {
                    if (mp.getValue() != null && mp.getValue() == 1) {
                        sort.and(Sort.by(mp.getKey()).ascending());
                    } else {
                        sort.and(Sort.by(mp.getKey()).descending());
                    }
                }
            }
            query.with(sort);
        }
        return query.addCriteria(criteria);
    }
}
